using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Admin.NET.Application.Entity;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Core;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;

namespace Admin.NET.Application.Service.Home;

/// <summary>
/// 首页服务
/// </summary>
[ApiDescriptionSettings(new string[] { "业务应用" }, Order = 100)]
public class HomeService : IDynamicApiController, ITransient, IPrivateDependency
{
	private readonly SqlSugarRepository<PowerConsumptionRecord> _rep;

	private readonly SqlSugarRepository<PaymentRecord> _repEnpter;

	public HomeService(SqlSugarRepository<PowerConsumptionRecord> rep, SqlSugarRepository<PaymentRecord> repEnpter)
	{
		_rep = rep;
		_repEnpter = repEnpter;
	}

	/// <summary>
	/// 首页统计
	/// </summary>
	/// <returns></returns>
	[HttpGet("/home/statistics")]
	public async Task<dynamic> GetStatistics()
	{
		DateTime now = DateTime.Now;
		DateTime monthBegin = DateTime.Parse($"{now.Year}-{now.Month}-1");
		DateTime beforeMonthBegin = monthBegin.AddMonths(-1);
		DateTime beforNow = now.AddMonths(-1);
		decimal nowTotal = await (from w in _rep.AsQueryable()
			where w.CreateTime >= monthBegin && w.CreateTime < now
			select w).SumAsync((PowerConsumptionRecord w) => w.CombinedActiveTotalElectricEnergyDifference);
		decimal beforeTotal = await (from w in _rep.AsQueryable()
			where w.CreateTime >= beforeMonthBegin && w.CreateTime < beforNow
			select w).SumAsync((PowerConsumptionRecord w) => w.CombinedActiveTotalElectricEnergyDifference);
		decimal totalQOQ = default(decimal);
		if (beforeTotal != 0m)
		{
			totalQOQ = Math.Round((nowTotal - beforeTotal) / beforeTotal * 100m, 2);
		}
		decimal nowIncome = await (from w in _repEnpter.Context.Queryable<PaymentRecord>()
			where w.CreateTime >= monthBegin && w.CreateTime < now && (w.IsPay == 1 || w.IsPay == 4)
			select w).SumAsync((PaymentRecord w) => w.Amount);
		decimal beforeIncome = await (from w in _repEnpter.Context.Queryable<PaymentRecord>()
			where w.CreateTime >= beforeMonthBegin && w.CreateTime < beforNow && (w.IsPay == 1 || w.IsPay == 4)
			select w).SumAsync((PaymentRecord w) => w.Amount);
		decimal incomeQOQ = default(decimal);
		if (beforeIncome != 0m)
		{
			incomeQOQ = Math.Round((nowIncome - beforeIncome) / beforeIncome * 100m, 2);
		}
		int meterTotal = await _repEnpter.Context.Queryable<ElectricMeter>().CountAsync();
		int onlineMeter = await (from w in _repEnpter.Context.Queryable<ElectricMeter>()
			where w.SignalStatus == 1
			select w).CountAsync();
		int collectorTotal = await _repEnpter.Context.Queryable<Admin.NET.Application.Collector>().CountAsync();
		int onlineCollector = await (from w in _repEnpter.Context.Queryable<Admin.NET.Application.Collector>()
			where w.Status == 1
			select w).CountAsync();
		return new
		{
			nowTotal = Math.Round(nowTotal, 2),
			beforeTotal = Math.Round(beforeTotal, 2),
			totalQOQ = totalQOQ,
			nowIncome = Math.Round(nowIncome, 2),
			beforeIncome = Math.Round(beforeIncome, 2),
			incomeQOQ = incomeQOQ,
			meterTotal = meterTotal,
			onlineMeter = onlineMeter,
			collectorTotal = collectorTotal,
			onlineCollector = onlineCollector
		};
	}

	/// <summary>
	/// 近一个月 top5用电量
	/// </summary>
	/// <returns></returns>
	[HttpGet("/home/top5powerconsumption")]
	public async Task<dynamic> GetTop5PowerConsumption()
	{
		DateTime today = DateTime.Today;
		DateTime lastmonth = today.AddMonths(-1);
		var data = await (from w in _rep.AsQueryable()
			where w.CreateTime >= lastmonth && w.CreateTime < today
			group w by new { w.Sn, w.Name } into w
			select new
			{
				Sn = w.Sn,
				Name = w.Name,
				Total = SqlFunc.AggregateSum(w.CombinedActiveTotalElectricEnergyDifference)
			} into w
			orderby w.Total descending
			select w).Take(5).ToListAsync();
		if (data.Count == 0)
		{
			return new
			{
				type = new List<int>(),
				data = new List<int>()
			};
		}
		_ = data[0].Total;
		return new
		{
			type = data.Select(s => s.Name),
			data = data.Select(s => new
			{
				name = s.Name,
				value = Math.Round(s.Total, 2)
			})
		};
	}

	/// <summary>
	/// 房间余额预警的房间用户
	/// </summary>
	/// <returns></returns>
	[HttpGet("/home/warningroom")]
	public async Task<dynamic> GetWarningRoom([FromQuery] BasePageInput input)
	{
		return await (from s in _repEnpter.Context.Queryable<Room>()
			where s.WarningRuleId != null && (s.Balance < 10m || s.LatestWarningBalance != null)
			orderby s.Balance
			select new RoomOutput
			{
				Name = s.Name,
				BuildingId = s.BuildingId,
				Area = s.Area,
				Balance = s.Balance,
				BuildingName = from s1 in SqlFunc.Subqueryable<Building>()
					where s1.Id == s.BuildingId
					select s1.Name,
				CreateTime = s.CreateTime,
				CreateUserId = s.CreateUserId,
				Id = s.Id,
				IsDelete = s.IsDelete,
				OwnerId = s.OwnerId,
				UpdateTime = s.UpdateTime,
				UpdateUserId = s.UpdateUserId,
				Remark = s.Remark,
				LatestWarningBalance = s.LatestWarningBalance,
				WarningRuleId = s.WarningRuleId,
				WarningRuleName = from s4 in SqlFunc.Subqueryable<WarningRule>()
					where (long?)s4.Id == s.WarningRuleId
					select s4.Name,
				OwnerName = from s2 in SqlFunc.Subqueryable<Owner>()
					where (long?)s2.Id == s.OwnerId
					select s2.Name,
				OwnerAccount = from s3 in SqlFunc.Subqueryable<Owner>()
					where (long?)s3.Id == s.OwnerId
					select s3.PhoneNumber
			}).ToPagedListAsync(input.Page, input.PageSize);
	}

	/// <summary>
	/// 获取管理方或物业待办内容
	/// </summary>
	/// <returns></returns>
	[HttpGet("/home/todolist")]
	public async Task<dynamic> GetToDoList()
	{
		return new
		{
			corporatePaymentCount = await (from w in _repEnpter.Context.Queryable<CorporatePayment>()
				where w.Status == 0
				select w).CountAsync(),
			invoiceIssuanceCount = await (from w in _repEnpter.Context.Queryable<BillRecord>()
				where w.Status == 0
				select w).CountAsync(),
			warningCount = await (from w in _repEnpter.Context.Queryable<EarlyWarning>()
				where w.Status == 0
				select w).CountAsync()
		};
	}
}
